<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模型拖拽的代码实例</title>
<style>
html,body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
</style>
</head>

<body>
<script type="importmap">
{
    "imports": {
        "three": "../js/threejs/three.module.js",
        "three/addons/": "../js/threejs/jsm/"
    }
}
</script>
<script type="module">
    import * as THREE from 'three';
    import { TrackballControls } from 'three/addons/controls/TrackballControls.js';
    import { DragControls } from 'three/addons/controls/DragControls.js';
    import { TransformControls } from 'three/addons/controls/TransformControls.js';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';//倒入轨道控制器
    import {RenderPass} from 'three/addons/postprocessing/RenderPass.js';
    import {OutlinePass} from 'three/addons/postprocessing/OutlinePass.js';
    import {EffectComposer} from 'three/addons/postprocessing/EffectComposer.js';

    import {GUI} from 'three/addons/libs/lil-gui.module.min.js';// 导入lil-gui
   
    import * as ThreeComm from '../js/three-comm.js';
    import threeUtil from '../js/three-cube.js';
    

const scene = new THREE.Scene()
let renderer = new THREE.WebGLRenderer({
  antialias: true,
  alpha: true,
  logarithmicDepthBuffer: true
})
let camera, controls, transformControl
var positionList= [
        [10, 0, 0],
        [-10, 0, 0]
      ]
const pointer = new THREE.Vector2()
const point = new THREE.Vector3()
const raycaster = new THREE.Raycaster()
let splineHelperObjects = []
const ARC_SEGMENTS = 200
let splines = []


init()
    addMarkModel()
    render()

    function init(){
      initHelper()
      initLight()
      initCamera()
      initRender()
      initControls()

      window.addEventListener('pointermove', e => {
        onPointerMove(e)
      })
    }
    function initHelper () {
      scene.background = new THREE.Color(0xf0f0f0)

      // const axes = new THREE.AxesHelper(50)
      // scene.add(axes)

      const planeGeometry = new THREE.PlaneGeometry(2000, 2000)
      planeGeometry.rotateX(-Math.PI / 2)
      const planeMaterial = new THREE.ShadowMaterial({ color: 0x000000, opacity: 0.2 })
      const plane = new THREE.Mesh(planeGeometry, planeMaterial)
      plane.position.y = -200
      plane.receiveShadow = true
      scene.add(plane)

      const helper = new THREE.GridHelper(2000, 100)
      helper.position.y = -199
      helper.material.opacity = 0.25
      helper.material.transparent = true
      scene.add(helper)
    }
    function initCamera () {
      camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        0.001,
        10000
      )
      camera.position.set(35, 35, 35)
    }
    function initLight () {
      const directLight = new THREE.DirectionalLight('#ffffff', 0.5)
      const directLight1 = new THREE.DirectionalLight('#ffffff', 0.5)
      const directLight2 = new THREE.PointLight('#ffffff', 0.5)
      const ambientLight = new THREE.AmbientLight('#ffffff', 0.3)

      directLight.castShadow = true
      directLight.position.set(15, 15, 15)
      directLight1.position.set(-15, -15, 15)
      ambientLight.position.set(0, 0, -5)
      directLight2.position.set(-15, 15, -15)
      directLight2.castShadow = true

      scene.add(directLight, directLight1, ambientLight, directLight2)
    }
    function initRender () {
      renderer.setSize(1902, 935)
      renderer.outputEncoding = THREE.sRGBEncoding
      document.body.appendChild(renderer.domElement)
    }
    function initControls () {
      controls = new OrbitControls(camera, renderer.domElement)

      transformControl = new TransformControls(camera, renderer.domElement)
      transformControl.addEventListener('change', () => {
        console.log('模型拖动')
      })
      transformControl.addEventListener('dragging-changed', function (event) {
        controls.enabled = !event.value
      })

      transformControl.addEventListener('objectChange', param => {
        this.updateSplineOutline()
      })
      scene.add(transformControl)
    }
    // 鼠标移动
    function onPointerMove (event) {
      pointer.x = (event.clientX / window.innerWidth) * 2 - 1
      pointer.y = -(event.clientY / window.innerHeight) * 2 + 1

      raycaster.setFromCamera(pointer, camera)

      const intersects = raycaster.intersectObjects(splineHelperObjects, false)

      if (intersects.length > 0) {
        const object = intersects[0].object

        if (object !== transformControl.object) {
          transformControl.attach(object)
          controls.enabled = false
        }
      }
    }
    // 更新连线
    function updateSplineOutline () {
      for (let k = 0; k < splines.length; k++) {
        const spline = splines[k]
        const splineMesh = spline.mesh
        const position = splineMesh.geometry.attributes.position
        for (let i = 0; i < ARC_SEGMENTS; i++) {
          const t = i / (ARC_SEGMENTS - 1)
          spline.getPoint(t, point)
          position.setXYZ(i, point.x, point.y, point.z)
        }
        position.needsUpdate = true
      }
    }
    function render () {
      requestAnimationFrame(render)
      controls.update()
      renderer.render(scene, camera)
    }
    function addMarkModel () {
      for (let i = 0; i < positionList.length; i++) {
        let position = []

        let obj1 = creatSpot(positionList[i], i)
        let obj2 = creatHtml(i)

        setTimeout(() => {
          position.push(obj1.position)
          position.push(obj2.position)
          creatLine(position)
        }, 2000)
      }
    }
    function creatSpot (positionArr, index) {
      const spherGeometry = new THREE.SphereGeometry(3, 32, 16)
      const spherMaterial = new THREE.MeshLambertMaterial({ color: 'red' })
      const sphere = new THREE.Mesh(spherGeometry, spherMaterial)
      sphere.position.set(positionArr[0], positionArr[1], positionArr[2])
      sphere.scale.set(0.2, 0.2, 0.2)
      splineHelperObjects.push(sphere)
      scene.add(sphere)
      return sphere
    }
    function creatHtml (index, spot) {
      const spherGeometry = new THREE.BoxGeometry(15, 15, 15)
      const spherMaterial = new THREE.MeshPhongMaterial({
        transparent: true,
        opacity: 1,
        color: 'green'
      })
      const sphere = new THREE.Mesh(spherGeometry, spherMaterial)

      sphere.position.x = Math.random() * 10
      sphere.position.y = Math.random() * 20
      sphere.position.z = Math.random() * 15
      sphere.scale.set(0.2, 0.2, 0.2)
      splineHelperObjects.push(sphere)
      scene.add(sphere)

      return sphere
    }
    function creatLine (position) {
      var curve = new THREE.CatmullRomCurve3(position)
      var points = curve.getPoints(ARC_SEGMENTS)
      var geometry = new THREE.BufferGeometry().setFromPoints(points)
      var material = new THREE.LineBasicMaterial({ color: 0xff0000 })

      curve.mesh = new THREE.LineSegments(geometry, material)
      scene.add(curve.mesh)
      splines.push(curve)
    }

</script>
</body>
</html>